package cn.bearspark.common.util;

import cn.bearspark.common.convert.ConvertInfo;
import cn.bearspark.common.enumeration.ConvertTypeEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 将原始数据转换成信息的工具类
 *
 * @author f
 */
public class ConvertInfoUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(ConvertInfoUtil.class);

    /**
     * 将 PO 转换成 DTO，并且为其中的某些必要字段进行转换
     *
     * @param src      PO 对象
     * @param tarClass DTO 的类对象
     * @param <T>      DTO 的类型
     * @return 含有 PO 信息的 DTO
     */
    public static <T> T convert(Object src, Class<T> tarClass) {
        if (src == null) {
            return null;
        }
        Class<?> srcClass = src.getClass();
        T tar = ConvertBeanUtil.convert(src, tarClass);
        Field[] fields = tarClass.getDeclaredFields();
        for (Field toField : fields) {
            // 跳过不用转换的字段
            if (!toField.isAnnotationPresent(ConvertInfo.class)) {
                continue;
            }

            // 获取转换时必要的信息
            ConvertInfo annotation = toField.getAnnotation(ConvertInfo.class);
            ConvertTypeEnum type = annotation.value();
            String fromAnno = annotation.from();
            String toAnno = annotation.to();

            // 获取字段在 DTO 中的名称
            String to = toAnno.isEmpty() ? toField.getName() : toAnno;
            // 获取字段在 PO 中的名称，该名称在 DTO 中以 Info 结尾
            String from = fromAnno.isEmpty() ? to.substring(0, to.lastIndexOf("Info")) : fromAnno;

            // 进行赋值
            try {
                Field fromField = srcClass.getDeclaredField(from);
                fromField.setAccessible(true);
                toField.setAccessible(true);
                Object value = null;
                if (ConvertTypeEnum.NUMBER == type) {
                    value = NumberInfoUtil.getNumberInfo((Long) fromField.get(src));
                } else if (ConvertTypeEnum.PAST_TIME == type) {
                    value = TimeInfoUtil.getPastTimeInfo((LocalDateTime) fromField.get(src));
                } else if (ConvertTypeEnum.FIXED_TIME == type) {
                    value = TimeInfoUtil.getFixedTimeInfo((LocalDateTime) fromField.get(src));
                } else if (ConvertTypeEnum.REMAINING_TIME == type) {
                    value = TimeInfoUtil.getRemainingTimeInfo((LocalDateTime) fromField.get(src));
                }
                toField.set(tar, value);
            } catch (NoSuchFieldException e) {
                LOGGER.error("[NoSuchFieldException]: from<{}> to<{}>", from, to);
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                LOGGER.error("[IllegalAccessException]: {}", e.getMessage());
                throw new RuntimeException(e);
            }
        }
        return tar;
    }

    /**
     * 将 PO 集合转换成 DTO 集合
     *
     * @param srcCollection PO 的集合
     * @param tarClass      DTO 的类对象
     * @param <T>           DTO 的类型
     * @return 含有 PO 信息的 DTO 集合
     */
    public static <T> List<T> convertList(Collection<?> srcCollection, Class<T> tarClass) {
        if (srcCollection == null || srcCollection.isEmpty()) {
            return new ArrayList<>();
        }
        List<T> tarList = new ArrayList<>(srcCollection.size());
        for (Object src : srcCollection) {
            T tar = convert(src, tarClass);
            tarList.add(tar);
        }
        return tarList;
    }

}
